using Joy.Erp.BasicArchives.Core.Events;
using Joy.Erp.BasicArchives.Core.UniqueCodes;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Settings;
using Volo.Abp.Uow;

namespace Joy.Erp.BasicArchives.ItemMasters
{
    public partial class UnitGroupManager : DomainService
    {
        protected IUnitGroupRepository UnitGroupRepository => LazyServiceProvider.LazyGetRequiredService<IUnitGroupRepository>();
        protected IDistributedEventBus DistributedEventBus => LazyServiceProvider.LazyGetRequiredService<IDistributedEventBus>();
        protected ISettingProvider SettingProvider => LazyServiceProvider.LazyGetRequiredService<ISettingProvider>();
        protected IUniqueCodeSetter UniqueCodeSetter => LazyServiceProvider.LazyGetRequiredService<IUniqueCodeSetter>();

        [UnitOfWork]
        public async Task<UnitGroup> CreateAsync(UnitGroup entity, bool autoSave = false, CancellationToken cancellationToken = default)
        {
            entity.SetId(GuidGenerator.Create());
            entity.TenantId = CurrentTenant.Id;

            foreach (var child in entity.Children)
            {
                child.SetId(GuidGenerator.Create());
                child.MainArchiveId = entity.Id;
            }

            if (entity.Code.IsNullOrWhiteSpace())
            {
                var uniqueCodeConfigration = await SettingProvider.GetOrNullAsync($"UniqueCodeConfigration:{typeof(UnitGroup).FullName}");
                UniqueCodeSetter.SetCode(entity, uniqueCodeConfigration);
            }

            await DistributedEventBus.PublishAsync(new EntityCreatingEto<UnitGroup>(entity), false);
            return await UnitGroupRepository.InsertAsync(entity, autoSave, cancellationToken);
        }

        [UnitOfWork]
        public async Task<UnitGroup> UpdateAsync(UnitGroup entity, bool autoSave = false, CancellationToken cancellationToken = default)
        {
            foreach (var child in entity.Children)
            {
                if (child.Id == Guid.Empty) child.SetId(GuidGenerator.Create());
                child.MainArchiveId = entity.Id;
            }

            await DistributedEventBus.PublishAsync(new EntityUpdatingEto<UnitGroup>(entity), false);

            return await UnitGroupRepository.UpdateAsync(entity, autoSave, cancellationToken);
        }

        [UnitOfWork]
        public async Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = default)
        {
            var entity = await UnitGroupRepository.GetAsync(id, true);

            await UnitGroupRepository.EnsureCollectionLoadedAsync(entity, x => x.Children, cancellationToken);
            entity.Children.Clear();

            await DistributedEventBus.PublishAsync(new EntityDeletingEto<UnitGroup>(entity), false);
            await UnitGroupRepository.DeleteAsync(entity, autoSave, cancellationToken);
        }
    }
}
